import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 苏李涛
 * Date: 2024-08-24
 * Time: 17:17
 */

/**
 * 四数之和:
 *
 * 给你一个由 n 个整数组成的数组 nums ，和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] （若两个四元组元素一一对应，则认为两个四元组重复）：
 *
 * 0 <= a, b, c, d < n
 * a、b、c 和 d 互不相同
 * nums[a] + nums[b] + nums[c] + nums[d] == target
 * 你可以按 任意顺序 返回答案 。
 *
 *
 *
 * 示例 1：
 *
 * 输入：nums = [1,0,-1,0,-2,2], target = 0
 * 输出：[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]
 * 示例 2：
 *
 * 输入：nums = [2,2,2,2,2], target = 8
 * 输出：[[2,2,2,2]]
 *
 *
 * 提示：
 *
 * 1 <= nums.length <= 200
 * -109 <= nums[i] <= 109
 * -109 <= target <= 109
 */
public class SumFourNum {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> ret = new ArrayList<>();
        //排序
        Arrays.sort(nums);


        int n = nums.length;
        for(int i = 0; i < n; ){//固定a

            //三数之和
            for(int j = i+1; j < n; ){//固定b


                //双指针,使sum ==  target-a-b
                int left = j+1;
                int right = n-1;
                long aim =(long)target-nums[i]-nums[j];
                while(left < right) {

                    int sum = nums[left] + nums[right];
                    if(sum > aim){
                        right--;
                    }else if(sum < aim) {
                        left++;
                    }else {
                        ret.add(Arrays.asList(nums[i],nums[j],nums[left],nums[right]));


                        //防找漏
                        left++;
                        right--;

                        //去重
                        while(left < right && nums[left-1] == nums[left]){
                            left++;
                        }
                        while(left < right && nums[right+1] == nums[right]){
                            right--;
                        }
                    }
                }

                j++;
                //去重
                while(j < n && nums[j-1] == nums[j]){
                    j++;
                }
            }

            i++;
            //去重
            while(i < n && nums[i-1] == nums[i]){
                i++;
            }

        }

        return ret;
    }
}
